package datensaetze;

import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Grundlegende Klasse: alles ist Datensatz.
 * 
 * Es gibt zwei Grundtypen, in Vorwegnahme der GND:
 * 		1. Titeldaten
 * 		2. Normdaten
 * 
 * Alle Kategorien (Felder) eines Datensatzes werden in die Map felder eingehängt. 
 * Enthält eine Kategorie einen Link auf einen anderen Datensatz, so enthält das
 * entsprechende Feld aus felder.values() einen Zeiger auf einen Datensatz:
 * 
 * :Datensatz:[("3000",Feld3000),...]
 * 							|
 * 							---> :Datensatz:[("100",Feld100),...]
 * 														|
 * 														-->"Müller,Anton"
 * 
 * Dieses Verfahren wird in der Regel angewandt auf die Kategorien (samt Analysatoren):
 * 
 * Titeldaten:
 * 	3000-3072 
 * @see GNDRecordFactory.createPersonAusExpansion	
 * 	3100-3188 (nicht implementiert)
 * 	4140, 4160, 4180, 4241-4245 (nicht implementiert)
 * 	5100-5199
 * @see GNDRecordFactory.createSWAusExpansion
 * (Klassifikationen passen nicht in dieses Schema und werden nicht berücksichtigt)
 * 
 * 	Normdaten:
 * 606
 * @see GNDRecordFactory.createSWAusExpansion
 * 850, 860, 870, 880
 * @see GNDRecordFactory.createSWAusSwFeld
 * 861, 862, 890, 892 (nicht implementiert)	
 * 
 * @author baumann
 *
 */
public class Datensatz {

	/**
	 * den Tags (z.B. 800, 808) werden Felder zugeordnet, die die Informationen
	 * strukturiert speichern. Wenn mehrere Tags einem Feld entsprechen (800,
	 * 801, ...), so wird es nur unter der magischen Nummer mainTag des zugehörigen 
	 * Analysators eingetragen. Diese Arbeit erledigt GNDRecordFactory.analyzeTag().
	 */
	private SortedMap<String, Feld> felder = new TreeMap<String, Feld>();

	public SortedMap<String, Feld> getFelder() {
		return Collections.unmodifiableSortedMap(felder);
	}

	private String rohdaten;

	private String idn = null;

	public String getIdn() {
		return idn;
	}

	/**
	 * Kann auch null sein, dann, wenn nicht nach
	 * Vorzugsbenennungen geparst wird. 
	 * 
	 * Die Vorzugsbenennung ergibt sich aus den Feldern 
	 * 800 ... 	bei Schlagwörtern (bez. indirekt bei Verlinkung)
	 * 601	   	bei Hinweisssätzen
	 * 4000 ?  	bei Titeldaten	
	 */
	private Feld vorzugsbenennung = null;

	public Feld getVorzugsbenennung() {
		return vorzugsbenennung;
	}

	public void setVorzugsbenennung(Feld vorzugsbenennung) {
		this.vorzugsbenennung = vorzugsbenennung;
	}

	public boolean contains(CharSequence cs) {
		if (vorzugsbenennung == null)
			return false;
		return vorzugsbenennung.contains(cs);
	}

	/**
	 * Liefert eine normierte Ansetzungsform ohne Bemerkungsfeld. 
	 * Damit sind Schlagwörter, die aus verschiedenen Quellen stammen 
	 * (Vollanzeige, Expansion und Felder wie 850 ...) miteinander 
	 * vergleichbar und können mittels String.equals() speichersparend 
	 * verglichen werden. 
	 * 
	 * Z
	 * 
	 * @return 	Ansetzung in der Form |<indikator>|<Inhalt1> / <Inhalt2> ..
	 */
	public String getAN() {
		if (vorzugsbenennung == null)
			return null;
		return vorzugsbenennung.getAN();
	}

	/**
	 * Für aus Verlinkung gewonnene Datensätze (sehr häufig in der 870/880)
	 */
	protected String bemerkung = null;

	public String getBemerkung() {
		return bemerkung;
	}

	void setBemerkung(String bemerkung) {
		this.bemerkung = bemerkung;
	}

	@Override
	public String toString() {
		String i = "Datensatz=[IDN=" + getIdn();
		String v = "";
		String b = "";
		if (vorzugsbenennung != null)
			v += vorzugsbenennung;
		else
			for (Feld feld : felder.values()) {
				v += feld;
			}
		if (v.length() > 0)
			v = ", " + v;
		if (bemerkung != null) {
			b += ", Bemerkung='" + bemerkung + "'";
		}
		return i + v + b + "]";
	}

	public String strukturiert() {
		String s = "IDN:\t" + getIdn();
		for (Feld feld : felder.values()) {
			s += "\n" + feld.strukturiert();
		}
		return s;
	}

	public Datensatz() {
		// TODO Auto-generated constructor stub
	}

	public String getRohdaten() {
		return rohdaten;
	}

	public Feld getFeld(String tag) {
		return felder.get(tag);
	}

	public void setFeld(String tag, Feld feld) {
		felder.put(tag, feld);
	}

	void removeFeld(String tag) {
		felder.remove(tag);
	}

	void loescheAlleFelder() {
		felder.clear();
	}

	public boolean istMehrgliedrig() {
		if (vorzugsbenennung != null)
			return vorzugsbenennung.istMehrgliedrig();
		else
			return false;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result =
			prime
				* result
				+ ((vorzugsbenennung == null) ? 0 : vorzugsbenennung
						.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Datensatz other = (Datensatz) obj;

		/*
		 * Die idn ist nicht enscheidend, da dann die Transitivität
		 * verletzt sein kann:
		 * !12!|s|a = !12!|p|b = |p|b <> !12!|s|a
		 */
		if (vorzugsbenennung == null)
			// Fehlende Vorzugsbenennungen kann man nicht vergleichen
			return false;
		if (vorzugsbenennung.equals(other.vorzugsbenennung))
			return true;
		return false;
	}

	/**
	 * @param idn the idn to set
	 */
	public void setIdn(String idn) {
		this.idn = idn;
	}

	/**
	 * @param rohdaten the rohdaten to set
	 */
	public void setRohdaten(String rohdaten) {
		this.rohdaten = rohdaten;
	}

}
